import java.io.IOException;
import java.util.Timer;
import java.util.TimerTask;

import javax.microedition.lcdui.Alert;
import javax.microedition.lcdui.AlertType;
import javax.microedition.lcdui.Display;
import javax.microedition.media.Manager;
import javax.microedition.media.MediaException;
import javax.microedition.media.Player;
import javax.microedition.media.PlayerListener;
import javax.microedition.midlet.MIDlet;
import javax.microedition.midlet.MIDletStateChangeException;

import com.nokia.mid.impl.isa.ui.DeviceControl;

public class LongPlayer extends MIDlet implements PlayerListener {

	private static final long ONE_SECOND = 1000000;
	private static final long ONE_MINUTE = 60 * ONE_SECOND;
	private static final long ONE_HOUR = 60 * ONE_MINUTE;
	private static LongPlayer instance;
	
	private LongPlayerScreen mainScreen;
	private Timer displayTimer;

	private Player player;
	private long playerTime;
	private long mediaLength = -1;
	private State state;

	private RestartManager restartManager;
	private Mp3File mp3;

	public LongPlayer() {
		instance = this;
		state = new State(State.IDLE);
		mainScreen = new LongPlayerScreen(this);
		restartManager = new RestartManager(this);
		DeviceControl.setLights(0, 100);
	}

	protected void destroyApp(boolean arg0) throws MIDletStateChangeException {
	}

	protected void pauseApp() {

	}

	protected void startApp() {
		Mp3File[] mp3List = MoviesListSetup.setup();
		PodcastListScreen podcastListScreen = new PodcastListScreen(mp3List);
		Display.getDisplay(this).setCurrent(podcastListScreen);
		podcastListScreen.repaint();		
	}

	private void playMp3() throws Throwable {
		restart(0);
	}

	public void secureKeyPressed(int keyCode) {
		try {
			keyPressed(keyCode);
		} catch (Throwable e) {
			e.printStackTrace();
		}
	}

	private void keyPressed(int keyCode) throws Throwable {
		long mediaTime = player.getMediaTime();

		if (mediaLength == -1) {
			mediaLength = player.getDuration();
		}

		if (keyCode == 49) {
			player.setMediaTime(mediaTime + ONE_MINUTE);
		} else if (keyCode == 50) {
			player.setMediaTime(mediaTime + ONE_MINUTE * 5);
		} else if (keyCode == 51) {
			player.setMediaTime(mediaTime + ONE_MINUTE * 15);
		} else if (keyCode == 54) {
			player.setMediaTime(mediaTime - ONE_MINUTE);
		} else if (keyCode == 53) {
			player.setMediaTime(mediaTime - ONE_MINUTE * 5);
		} else if (keyCode == 52) {
			player.setMediaTime(mediaTime - ONE_MINUTE * 15);
		} else if (keyCode == 56) {
			if (LongPlayer.getState().equals(State.PAUSE)) {
				play();
			} else if (LongPlayer.getState().equals(State.PLAY)) {
				pause();
			}
		}
		mainScreen.repaint();
	}

	public static LongPlayer getInstance() {
		return instance;
	}

	public void searchChoiceCompleted(Mp3File aMp3) {
		try {
			mp3 = aMp3;
			Display.getDisplay(this).setCurrent(mainScreen);
			MediaMark mark = Config.getMediaMark();
			
			if ((mark != MediaMark.NO_MEDIA_MARK)
				&& (mp3.getName().equals(mark.getName()))) {
				restart(mark.getPos());
			} else {
				playMp3();
			}
		} catch (Throwable e) {
			e.printStackTrace();
		}
	}



	private String getFormattedTime(long time) {
		long numHour = time / ONE_HOUR;
		long numMin = (time - numHour * ONE_HOUR) / ONE_MINUTE;
		long numSec = (time - numHour * ONE_HOUR - numMin
				* ONE_MINUTE)
				/ ONE_SECOND;
		return format(numHour) + ":" + format(numMin) + ":"
				+ format(numSec);
	}

	private String format(long value) {
		String result = Long.toString(value);
		if (value < 10) {
			result = "0" + Long.toString(value);
		}
		return result;
	}
	
	public void playerUpdate(Player arg0, String event, Object arg2) {
		if (PlayerListener.END_OF_MEDIA.equals(event)) {
			Config.deleteMediaMark();
			notifyDestroyed();
		} else if (PlayerListener.DEVICE_UNAVAILABLE.equals(event)) {
			displayTimer.cancel();
			restartManager.restartPlayer(playerTime);
		} else if (PlayerListener.DURATION_UPDATED.equals(event)) {
			mediaLength = player.getDuration();
		}
	}

	private void debugAlert(String message) {
		Alert alert = new Alert("Debug", message, null, AlertType.INFO);
		Display display = Display.getDisplay(this);
		display.setCurrent(alert, mainScreen);
	}
	
	public void restart(long time) throws MediaException {
		try {
			player = Manager.createPlayer(mp3.getFullPath());
		} catch (IOException e) {
			debugAlert(e.getClass().getName());
		}
		player.realize();
		player.prefetch();
		player.setMediaTime(time);
		player.start();
		state.remove(State.PAUSE);
		state.add(State.PLAY);
		player.addPlayerListener(this);
		
		mainScreen.setTotalTime(player.getDuration());
		displayTimer = new Timer();
		displayTimer.schedule(new TimerTask() {

			public void run() {
				playerTime = player.getMediaTime();
				Config.setMediaMark(mp3.getName(), playerTime);
				mainScreen.setActualTime(playerTime);
				String formattedTime = getFormattedTime(playerTime);
				mainScreen.setTime(formattedTime);
				mainScreen.repaint();
			}

		}, 1000, 1000);
	}


	public static void show(String message) {
		instance.debugAlert(message);
	}
	public static void showException(Throwable e) {
		instance.debugAlert(e.getClass().getName());
	}

	public static State getState() {
		return getInstance().state;
	}

	public void play() {
		state.remove(State.PAUSE);
		state.add(State.PLAY);
		try {
			player.start();
		} catch (MediaException e) {
			LongPlayer.showException(e);
		}
	}

	public void pause() {
		state.remove(State.PLAY);
		state.add(State.PAUSE);
		try {
			player.stop();
		} catch (MediaException e) {
			LongPlayer.showException(e);
		}
	}

}
